/*
 *
 *  * Copyright (C) 2021 Huawei Device Co., Ltd.
 *  * Licensed under the Apache License, Version 2.0 (the "License");
 *  * you may not use this file except in compliance with the License.
 *  * You may obtain a copy of the License at
 *  *
 *  *     http://www.apache.org/licenses/LICENSE-2.0
 *  *
 *  * Unless required by applicable law or agreed to in writing, software
 *  * distributed under the License is distributed on an "AS IS" BASIS,
 *  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  * See the License for the specific language governing permissions and
 *  * limitations under the License.
 *  *
 *
 */

package com.xuexiang.xui_lib.component.textview.marqueen;

import ohos.agp.animation.AnimatorValue;
import ohos.agp.components.AttrSet;
import ohos.agp.components.Component;
import ohos.agp.components.ComponentContainer;
import ohos.agp.components.DirectionalLayout;
import ohos.agp.components.Image;
import ohos.agp.components.Text;
import ohos.agp.components.element.Element;
import ohos.app.Context;
import ohos.app.dispatcher.TaskDispatcher;
import ohos.app.dispatcher.task.TaskPriority;
import ohos.utils.PlainBooleanArray;

import com.xuexiang.xui_lib.ResourceTable;
import com.xuexiang.xui_lib.util.TextUtils;

/**
 * 可伸缩折叠的TextViewo
 *
 * @since 2021-04-07
 */
public class ExpandableTextComponent extends DirectionalLayout implements Component.ClickedListener {
    /* The default number of lines */
    private static final int MIX_COLLAPSED_LINES = 5;

    private static final int MAX_COLLAPSED_LINES = 11;

    /* The default animation duration */
    private static final int DEFAULT_ANIM_DURATION = 1000;

    /* The default alpha value when the animation starts */
    private static final float DEFAULT_ANIM_ALPHA_START = 0.7f;
    private static final int DEFAULT_TEXT_SIZE = 530;
    private static final int DEFAULT_COLLAPSED_HEIGHT = 350;
    private static final int MAX_HEIGHT = 750;
    private static final int TWO = 2;
    private static final int TEXT_SIZE = 44;

    protected Text mTv;

    protected Image mButton; // Button to expand/collapse

    private boolean isReLayout;

    private boolean isCollapsed = true; // Show short version as default.

    private int mCollapsedHeight;

    /*private int end;

    private int start;*/

    private int mTextHeightWithMaxLines;

    private int mMaxCollapsedLines;

    private int mMarginBetweenTxtAndBottom;

    private Element mExpandDrawable;

    private Element mCollapseDrawable;

    //private int mAnimationDuration;

    //private float mAnimAlphaStart;

//    private boolean isAnimating;

    /* Listener for callback */
    private OnExpandStateChangeListener mListener;

    /* For saving collapsed status when used in ListView */
    private PlainBooleanArray mCollapsedStatus;
    private int mPosition;

    /**
     * 构造方法
     *
     * @param context 上下文
     */
    public ExpandableTextComponent(Context context) {
        super(context);
        init(null);
    }

    /**
     * 构造方法
     *
     * @param context 上下文
     * @param attrSet 自定义属性
     */
    public ExpandableTextComponent(Context context, AttrSet attrSet) {
        super(context, attrSet);
        init(attrSet);
    }

    /**
     * 构造方法
     *
     * @param context 上下文
     * @param attrSet 自定义属性
     * @param styleName 风格名称
     */
    public ExpandableTextComponent(Context context, AttrSet attrSet, String styleName) {
        super(context, attrSet, styleName);
        init(attrSet);
    }

    @Override
    public void setOrientation(int orientation) {
        if (orientation == DirectionalLayout.HORIZONTAL) {
            throw new IllegalArgumentException("ExpandableTextView only supports Vertical Orientation.");
        }
        super.setOrientation(orientation);
    }

    private void init(AttrSet attrs) {
        initAttr(attrs);

        // enforces vertical orientation
        setOrientation(DirectionalLayout.VERTICAL);

        // default visibility is gone
        setVisibility(HIDE);
    }

    private void initAttr(AttrSet attrs) {
        if (attrs != null) {
            if (attrs.getAttr("max_text_lines").isPresent()) {
                mMaxCollapsedLines = attrs.getAttr("max_text_lines").get().getIntegerValue();
            } else {
                mMaxCollapsedLines = 1;
            }
            if (attrs.getAttr("animation_duration").isPresent()) {
                //mAnimationDuration = attrs.getAttr("animation_duration").get().getIntegerValue();
            } else {
                //mAnimationDuration = DEFAULT_ANIM_DURATION;
            }
            if (attrs.getAttr("anim_alpha_start").isPresent()) {
                //mAnimAlphaStart = attrs.getAttr("anim_alpha_start").get().getIntegerValue();
            } else {
                //mAnimAlphaStart = DEFAULT_ANIM_ALPHA_START;
            }
        }

        setEstimateSizeListener(new EstimateSizeListener() {
            @Override
            public boolean onEstimateSize(int i, int i1) {
                if (!isReLayout || getVisibility() == Component.HIDE) {
                    return false;
                }
                isReLayout = false;
                mButton.setVisibility(Component.HIDE);
                mTv.setMaxTextLines(Integer.MAX_VALUE);
                if (mTv.getMaxTextLines() <= mMaxCollapsedLines) {
                    return false;
                }
                mTextHeightWithMaxLines = getRealTextViewHeight(mTv);

                if (isCollapsed) {
                    mTv.setMaxTextLines(mMaxCollapsedLines);
                }

                mButton.setVisibility(Component.VISIBLE);

                // Re-measure with new setup

                if (isCollapsed) {
                    TaskDispatcher globalTaskDispatcher = mContext.getGlobalTaskDispatcher(TaskPriority.DEFAULT);
                    globalTaskDispatcher.syncDispatch(new Runnable() {
                        @Override
                        public void run() {
                            mMarginBetweenTxtAndBottom = getHeight() - mTv.getHeight();
                        }
                    });
                    mCollapsedHeight = DEFAULT_COLLAPSED_HEIGHT;
                }
                return false;
            }
        });
    }

    /**
     * 绑定组件
     *
     * @param text 文本
     * @param button 按钮
     */
    public void findViews(Text text, Image button) {
        mTv = text;
        mButton = button;
        mTv.setClickedListener(this);
        mButton.setPixelMap(isCollapsed ? ResourceTable.Media_xui_ic_expand_more_black_12dp : ResourceTable
            .Media_xui_ic_expand_less_black_12dp);
        mButton.setClickedListener(this);
        mTv.setTextSize(TEXT_SIZE);
    }

    @Override
    public void onClick(Component component) {
        if (mButton.getVisibility() != Component.VISIBLE) {
            return;
        }
        isCollapsed = !isCollapsed;
        mButton.setPixelMap(isCollapsed ? ResourceTable.Media_xui_ic_expand_more_black_12dp : ResourceTable
            .Media_xui_ic_expand_less_black_12dp);
        if (mCollapsedStatus != null) {
            mCollapsedStatus.put(mPosition, isCollapsed);
        }
        AnimatorValue animatorValue = new AnimatorValue();
        animatorValue.setValueUpdateListener(new AnimatorValue.ValueUpdateListener() {
            @Override
            public void onUpdate(AnimatorValue animatorValue, float value) {
                int mEndHeight;
                if (isCollapsed) {
                    mEndHeight = mCollapsedHeight;
                } else {
                    mEndHeight = getHeight() + mTextHeightWithMaxLines - mTv.getHeight() / TWO;
                }

                int newHeight = (int) ((mEndHeight - getHeight()) * value + getHeight());
                if (newHeight > MAX_HEIGHT) {
                    newHeight = MAX_HEIGHT;
                }
                mTv.setMaxTextHeight(newHeight - mMarginBetweenTxtAndBottom);
                mTv.setMaxTextLines(isCollapsed ? MIX_COLLAPSED_LINES : MAX_COLLAPSED_LINES);
                ComponentContainer.LayoutConfig layoutConfig = getLayoutConfig();
                layoutConfig.height = newHeight;
                setLayoutConfig(layoutConfig);
            }
        });
        animatorValue.setDuration(DEFAULT_ANIM_DURATION);
        animatorValue.start();
        if (mListener != null) {
            mListener.onExpandStateChanged(mTv, !isCollapsed);
        }
    }

    /**
     * 设置伸展状态监听
     *
     * @param listener
     */
    public void setOnExpandStateChangeListener(OnExpandStateChangeListener listener) {
        mListener = listener;
    }

    /**
     * 设置文本内容
     *
     * @param text 文本内容
     */
    public void setText(CharSequence text) {
        isReLayout = true;
        mTv.setText(String.valueOf(text));
        setVisibility(TextUtils.isEmpty(text) ? Component.HIDE : Component.VISIBLE);
    }

    /**
     * 设置文本内容
     *
     * @param text 文本内容
     * @param collapsedStatus 伸缩状态
     * @param position 位置
     */
    public void setText(CharSequence text, PlainBooleanArray collapsedStatus, int position) {
        mCollapsedStatus = collapsedStatus;
        mPosition = position;
        boolean isCollapse = collapsedStatus.get(position, true);
        isCollapsed = isCollapse;
        mButton.setImageElement(this.isCollapsed ? mExpandDrawable : mCollapseDrawable);
        setText(text);
        getLayoutConfig().height = ComponentContainer.LayoutConfig.MATCH_CONTENT;
        postLayout();
    }

    /**
     * 获取文本内容
     *
     * @return 文本内容
     */
    public CharSequence getText() {
        if (mTv == null) {
            return "";
        }
        return mTv.getText();
    }

    private int getRealTextViewHeight(Text textView) {
        int textHeight = DEFAULT_TEXT_SIZE;
        int padding = textView.getPaddingTop() + textView.getPaddingBottom();
        return textHeight + padding;
    }

    private static void applyAlphaAnimation(Component view, float alpha) {
        AnimatorValue alphaAnimation = new AnimatorValue();
        alphaAnimation.setDuration(0);
        alphaAnimation.start();
    }

    /**
     * 伸缩标记监听接口
     *
     * @since 2021-04-10
     */
    public interface OnExpandStateChangeListener {
        /**
         * 动画完成
         *
         * @param textView 伸缩的文本view
         * @param isExpanded 伸缩标志
         */
        void onExpandStateChanged(Text textView, boolean isExpanded);
    }
}
